package com.zhiche.wms.service.log.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.wms.configuration.MyConfigurationProperties;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.RestfulResponse;
import com.zhiche.wms.core.supports.enums.InterfaceAddrEnum;
import com.zhiche.wms.core.supports.enums.SysSourceEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.HttpClientUtil;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.inbound.FactoryPrepareInboundMapper;
import com.zhiche.wms.domain.mapper.stock.SkuMapper;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.domain.model.inbound.FactoryPrepareInbound;
import com.zhiche.wms.domain.model.inbound.InboundNoticeHeader;
import com.zhiche.wms.domain.model.inbound.InboundNoticeLine;
import com.zhiche.wms.domain.model.log.ItfImplogHeader;
import com.zhiche.wms.domain.model.log.ItfImplogLine;
import com.zhiche.wms.domain.model.opbaas.OpDeliveryPoint;
import com.zhiche.wms.domain.model.opbaas.OpTask;
import com.zhiche.wms.domain.model.otm.OtmOrderRelease;
import com.zhiche.wms.domain.model.otm.OtmShipment;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeHeader;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeLine;
import com.zhiche.wms.domain.model.outbound.OutboundPrepareLine;
import com.zhiche.wms.dto.opbaas.resultdto.ReleaseDTO;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.base.IStorehouseService;
import com.zhiche.wms.service.constant.*;
import com.zhiche.wms.service.dto.OriginationDTO;
import com.zhiche.wms.service.dto.ShipTaskDTO;
import com.zhiche.wms.service.dto.ShipmentDTO;
import com.zhiche.wms.service.inbound.IInboundNoticeHeaderService;
import com.zhiche.wms.service.inbound.IInboundNoticeLineService;
import com.zhiche.wms.service.inbound.IInboundPutawayHeaderService;
import com.zhiche.wms.service.log.IItfImplogHeaderService;
import com.zhiche.wms.service.log.IItfImplogLineService;
import com.zhiche.wms.service.log.ImportShipment;
import com.zhiche.wms.service.opbaas.IDeliveryPointService;
import com.zhiche.wms.service.opbaas.IOrderReleaseService;
import com.zhiche.wms.service.opbaas.ITaskService;
import com.zhiche.wms.service.otm.IOtmOrderReleaseService;
import com.zhiche.wms.service.otm.IOtmShipmentService;
import com.zhiche.wms.service.outbound.IOutboundNoticeHeaderService;
import com.zhiche.wms.service.outbound.IOutboundNoticeLineService;
import com.zhiche.wms.service.outbound.IOutboundPrepareLineService;
import com.zhiche.wms.service.stock.IStockService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class ImportShipmentImpl implements ImportShipment {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImportShipmentImpl.class);
    @Autowired
    private MyConfigurationProperties properties;
    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IBusinessDocNumberService businessDocNumberService;
    @Autowired
    private IStorehouseService storehouseService;

    @Autowired
    private IItfImplogHeaderService itfImplogHeaderService;
    @Autowired
    private IItfImplogLineService itfImplogLineService;

    @Autowired
    private IOtmShipmentService otmShipmentService;

    @Autowired
    private IOtmOrderReleaseService otmOrderReleaseService;

    @Autowired
    private IDeliveryPointService deliveryPointService;

    @Autowired
    private ITaskService taskService;

    @Autowired
    private IOutboundNoticeHeaderService outboundNoticeHeaderService;

    @Autowired
    private IOutboundNoticeLineService outboundNoticeLineService;

    @Autowired
    private IInboundNoticeHeaderService inboundNoticeHeaderService;

    @Autowired
    private IInboundNoticeLineService inboundNoticeLineService;

    @Autowired
    private IOutboundPrepareLineService outboundPrepareLineService;
    @Autowired
    private IOrderReleaseService iOrderReleaseService;
    @Autowired
    private FactoryPrepareInboundMapper factoryPrepareInboundMapper;
    @Autowired
    private IStockService iStockService;
    @Autowired
    private IInboundPutawayHeaderService iInboundPutawayHeaderService;
    @Autowired
    private SkuMapper skuMapper;

    @Override
    public void importOTMShipment(ShipmentDTO shipmentDTO) {
        LOGGER.info("接口指令开始importOTMShipment入参shipmentDTO为：{}",shipmentDTO);
        HashMap<String, Long> logLineCache = Maps.newHashMap();
        LOGGER.info("操作指令类型为：transactionCode :{},运单数据为：{}",shipmentDTO.getTransactionCode(),shipmentDTO.getShipTaskDTOList()==null?"为空":shipmentDTO.getShipTaskDTOList().size());
        if("RC".equals(shipmentDTO.getTransactionCode()) || ("R".equals(shipmentDTO.getTransactionCode()) && CollectionUtils.isEmpty(shipmentDTO.getShipTaskDTOList()))){

            //插入日志
            ItfImplogHeader header = getLogHeader(shipmentDTO, logLineCache, "删除");
            new Thread(() -> {
                itfImplogHeaderService.insert(header);
                if(CollectionUtils.isNotEmpty(header.getItfImplogLineList())){
                    itfImplogLineService.insertBatch(header.getItfImplogLineList());
                }
            }).start();
          //获取otm里的指令和指令下的运单
            OtmShipment dbShipment = getDBShipment(shipmentDTO);
            if(Objects.nonNull(dbShipment)){
                if (dbShipment.getShipmentType().equals(OtmShipmentType.PICK_UP)) { //循环删除提车指令
                    for (OtmOrderRelease otmOrderRelease : dbShipment.getOtmOrderReleaseList()){
                        delTask(otmOrderRelease);
                    }
                }
                delOutNoticeByShipment(dbShipment,null);//删除出入库通知单
                delInNoticeByShipment(dbShipment,null);//删除入入库通知单
                delShipment(dbShipment); //删除指令
            }
        }else if("IU".equals(shipmentDTO.getTransactionCode())
                || "R".equals(shipmentDTO.getTransactionCode())) {
            updateOTMShipment(shipmentDTO);

        }else {
            LOGGER.error("推送指令类型:{},不支持此类型操作", shipmentDTO.getTransactionCode());
        }
    }

    @Override
    public void updateReleaseInfo (ReleaseDTO releaseDTOs) {
        iOrderReleaseService.updateReleaseInfo(releaseDTOs);
    }

    private void updateOTMShipment(ShipmentDTO shipmentDTO){
        HashMap<String, Long> logLineCache = Maps.newHashMap();
        String orderType = shipmentDTO.getTransactionCode();
        //插入日志
        ItfImplogHeader logHeader = getLogHeader(shipmentDTO, logLineCache, orderType);
        new Thread(() -> {
            itfImplogHeaderService.insert(logHeader);
            if(CollectionUtils.isNotEmpty(logHeader.getItfImplogLineList())){
                itfImplogLineService.insertBatch(logHeader.getItfImplogLineList());
            }
        }).start();

        //构建otm数据
        OtmShipment newOtmShipment = getOtmShipment(shipmentDTO, logHeader, logLineCache);
        //将shipment下的数据复制给wms里的dbshipment
        OtmShipment dbShipment = getDBShipment(shipmentDTO);
        OtmShipment newShipment = null;
        if(Objects.isNull(dbShipment)){
            //一条新的otmshipment并且包含了日志信息
            newShipment = newOtmShipment;
        }else {
            /*
             otm指令信息和wms数据库指令信息对比
             */
            //newshipment包含了两个的并集
            newShipment = compareShipment(newOtmShipment,dbShipment);
            newShipment.setId(dbShipment.getId());
        }

        //循环处理指令
        if(Objects.isNull(dbShipment)){
            newOtmShipment.setId(snowFlakeId.nextId());
            otmShipmentService.insert(newShipment);
            newOtmShipment.setDataStatus(TableStatusEnum.STATUS_10.getCode());

            for (OtmOrderRelease otmOrderRelease : newShipment.getOtmOrderReleaseList()){
                otmOrderRelease.setId(snowFlakeId.nextId());
                otmOrderRelease.setDataStatus(TableStatusEnum.STATUS_10.getCode());
                otmOrderReleaseService.insert(otmOrderRelease);

            }
        }else {
            for (OtmOrderRelease otmOrderRelease : newShipment.getOtmOrderReleaseList()){
                if(otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_10.getCode())){
                    otmOrderRelease.setId(snowFlakeId.nextId());
                    otmOrderRelease.setDataStatus(TableStatusEnum.STATUS_10.getCode());
                    otmOrderRelease.setRemarks("指令新增");
                    otmOrderReleaseService.insert(otmOrderRelease);
                }
                if(otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_50.getCode())){
                    OtmOrderRelease delRelease = new OtmOrderRelease();
                    delRelease.setRemarks("指令删除");
                    delRelease.setId(otmOrderRelease.getId());
                    delRelease.setStatus(TableStatusEnum.STATUS_50.getCode());
                    otmOrderReleaseService.updateById(delRelease);
                }
            }
            //修改shipment
            otmShipmentService.updateById(newShipment);
        }

        //循环处理提车段任务
        if(newShipment.getShipmentType().equals(OtmShipmentType.PICK_UP)){
            for(OtmOrderRelease otmOrderRelease : newShipment.getOtmOrderReleaseList()) {

                //删除任务
                if (otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_50.getCode())){
                    delTask(otmOrderRelease);
                }
            }
            for(OtmOrderRelease otmOrderRelease : newShipment.getOtmOrderReleaseList()) {
                //创建新任务
                if(otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_10.getCode())){
                    Wrapper<OpDeliveryPoint> ew = new EntityWrapper<>();
                    ew.eq("code", otmOrderRelease.getOriginLocationGid());
                    OpDeliveryPoint deliveryPoint = deliveryPointService.selectOne(ew);
                    buildTask(otmOrderRelease, deliveryPoint);
                }
            }
        }

        ArrayList<String> originLocationList = Lists.newArrayList();
        ArrayList<String> destLocationList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(newShipment.getOtmOrderReleaseList())) {
            for (OtmOrderRelease otmOrderRelease : newShipment.getOtmOrderReleaseList()) {
                originLocationList.add(otmOrderRelease.getOriginLocationGid());
                destLocationList.add(otmOrderRelease.getDestLocationGid());
                //指令下发仓库不存在的情况下去integration系统同步仓库
                checkShipmentStoreHouse(destLocationList);
            }
        }


        // 发货仓库
        EntityWrapper<Storehouse> ewOut = new EntityWrapper<>(); //发货仓库条件
        ewOut.eq("status", TableStatusEnum.STATUS_10.getCode()).in("code", originLocationList);
        List<Storehouse> originHouses = storehouseService.selectList(ewOut);  //发货仓库列表

        // 收货仓库列表
        EntityWrapper<Storehouse> ewIn = new EntityWrapper<>();  //收货仓库条件
        ewIn.eq("status", TableStatusEnum.STATUS_10.getCode()).in("code", destLocationList);
        List<Storehouse> destHouses = storehouseService.selectList(ewIn);

        //分组出库指令
        List<OtmShipment> outboundShipments = getOutboundShipment(originHouses,newShipment);

        //分组入库指令
        List<OtmShipment> inboundShipments = getInboundShipment(destHouses,newShipment);

        //循环处理出库通知单
        for(OtmShipment outShipment : outboundShipments){
            updateOutboundNotice(outShipment,originHouses);
        }

        //循环处理入库通知单
        for(OtmShipment inShipment : inboundShipments){
            updateInboundNotice(inShipment,destHouses);
        }

        //订单信息同步出入库信息
        if("R".equals(orderType)){
            updateNoticeCusOrderNo(newShipment);
            //通知指令状态
            updateShipmentStatus(newShipment.getShipmentGid());
        }
    }

    /**
     * 检查仓库是否存在
     *
     * @param destLocationList 目的地仓库
     */
    private void checkShipmentStoreHouse (ArrayList<String> destLocationList) {
        try {
            List<String> storeHouseList = new ArrayList();
            storeHouseList = destLocationList;
            HashSet storeHash = new HashSet(storeHouseList);
            storeHouseList.clear();
            storeHouseList.addAll(storeHash);
            EntityWrapper<Storehouse> storeEw = new EntityWrapper<>();
            storeEw.eq("status", TableStatusEnum.STATUS_10.getCode()).in("code", storeHouseList);
            List<Storehouse> destStoreList = storehouseService.selectList(storeEw);
            for (String storeCode : storeHouseList) {
                if ((storeCode.contains("库") || storeCode.contains("站")) && !destStoreList.contains(storeCode)) {
                    //integration查询仓库是否存在
                    Map<String, Object> param = new HashMap<>();
                    Map<String, Object> condition = new HashMap<>();
                    condition.put("code", storeCode);
                    param.put("condition", condition);
                    String result = HttpClientUtil.postJson(properties.getIntegrationhost() + InterfaceAddrEnum.QUERY_STORE_HOUSE.getAddress(), null, JSONObject.toJSONString(param), properties.getSocketTimeOut());
                    if (StringUtils.isNotEmpty(result)) {
                        RestfulResponse<Page<OriginationDTO>> restfulResponse = JSON.parseObject(result,
                                new TypeReference<RestfulResponse<Page<OriginationDTO>>>() {
                                });
                        if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                            //新增WMS仓库
                            OriginationDTO oriRes = restfulResponse.getData().getRecords().get(0);
                            Storehouse storehouse = new Storehouse();
                            storehouse.setId(snowFlakeId.nextId());
                            storehouse.setCode(oriRes.getCode());
                            storehouse.setName(oriRes.getName());
                            storehouse.setProvince(oriRes.getProvince());
                            storehouse.setCity(oriRes.getCity());
                            storehouse.setCounty(oriRes.getCounty());
                            storehouse.setAddress(oriRes.getAddress());
                            storehouse.setLinkMan(oriRes.getContact());
                            storehouse.setLinkPhone(oriRes.getPhone());
                            storehouse.setUserCreate("ADMIN");
                            storehouseService.insert(storehouse);
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("新增仓库异常", e.getMessage());
        }
    }
    //通知指令状态
    private void updateShipmentStatus (String shipmentGid) {
        LOGGER.info("更新指令状态shipmentGid：{}", shipmentGid);
        new Thread(() -> {
            EntityWrapper<OtmOrderRelease> releaseEW = new EntityWrapper<>();
            releaseEW.eq("shipment_gid",shipmentGid);
            releaseEW.ne("status",TableStatusEnum.STATUS_50.getCode());
            releaseEW.isNull("ship_date");
            List<OtmOrderRelease> otmOrderReleases = otmOrderReleaseService.selectList(releaseEW);
            if(CollectionUtils.isEmpty(otmOrderReleases)){
                OtmShipment otmShipment = new OtmShipment();
                otmShipment.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
                EntityWrapper<OtmShipment> otmShipmentEntityWrapper = new EntityWrapper<>();
                otmShipmentEntityWrapper.eq("shipment_gid",shipmentGid);
                otmShipmentEntityWrapper.ne("status",TableStatusEnum.STATUS_50.getCode());
                otmShipmentService.update(otmShipment,otmShipmentEntityWrapper);
            }
        }).start();
    }

    private void updateNoticeCusOrderNo (OtmShipment newShipment) {
        try {
            String shipmentGid = newShipment.getShipmentGid();
            //查询入库通知单头表信息
            EntityWrapper<InboundNoticeHeader> inboundHeaderEw = new EntityWrapper<>();
            inboundHeaderEw.eq("source_key", shipmentGid);
            inboundHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
            List<InboundNoticeHeader> inboundNoticeHeaders = inboundNoticeHeaderService.selectList(inboundHeaderEw);

            //查询出库通知单头表信息
            EntityWrapper<OutboundNoticeHeader> outboundHeaderEw = new EntityWrapper<>();
            outboundHeaderEw.eq("source_key", shipmentGid);
            outboundHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
            List<OutboundNoticeHeader> outboundNoticeHeaders = outboundNoticeHeaderService.selectList(outboundHeaderEw);

            // 获取指令信息
            List<OtmOrderRelease> otmOrderReleases = newShipment.getOtmOrderReleaseList();
            for (OtmOrderRelease otmOrderRelease : otmOrderReleases) {
                //同步入库订单数据
                if (CollectionUtils.isNotEmpty(inboundNoticeHeaders)) {
                    for (InboundNoticeHeader inboundNoticeHeader : inboundNoticeHeaders) {
                        EntityWrapper<InboundNoticeLine> inboundLineEw = new EntityWrapper<>();
                        inboundLineEw.eq("header_id", inboundNoticeHeader.getId());
                        inboundLineEw.eq("line_source_key", otmOrderRelease.getReleaseGid());
                        inboundLineEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                        InboundNoticeLine inboundNoticeLine = inboundNoticeLineService.selectOne(inboundLineEw);
                        if (null != inboundNoticeLine) {
                            if (!otmOrderRelease.getCusOrderNo().equals(inboundNoticeLine.getOwnerOrderNo())) {
                                InboundNoticeLine inboundParam = new InboundNoticeLine();
                                inboundParam.setId(inboundNoticeLine.getId());
                                inboundParam.setOwnerOrderNo(otmOrderRelease.getCusOrderNo());
                                inboundNoticeLineService.updateById(inboundParam);
                            }
                        }
                    }
                }

                if (CollectionUtils.isNotEmpty(outboundNoticeHeaders)) {
                    for (OutboundNoticeHeader outboundNoticeHeader : outboundNoticeHeaders) {
                        EntityWrapper<OutboundNoticeLine> outboundLineEw = new EntityWrapper<>();
                        outboundLineEw.eq("header_id", outboundNoticeHeader.getId());
                        outboundLineEw.eq("line_source_key", otmOrderRelease.getReleaseGid());
                        outboundLineEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                        OutboundNoticeLine outboundNoticeLine = outboundNoticeLineService.selectOne(outboundLineEw);
                        if (null != outboundNoticeLine) {
                            if (!otmOrderRelease.getCusOrderNo().equals(outboundNoticeLine.getOwnerOrderNo())) {
                                OutboundNoticeLine outboundParam = new OutboundNoticeLine();
                                outboundParam.setId(outboundNoticeLine.getId());
                                outboundParam.setOwnerOrderNo(otmOrderRelease.getCusOrderNo());
                                outboundNoticeLineService.updateById(outboundParam);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("指令下发更新出入库通知单的客户订单号异常",e.getMessage());
        }
    }

    /**
     * 构建提车段任务
     * @param newOrderRelease
     * @param deliveryPoint
     */
    private void buildTask(OtmOrderRelease newOrderRelease, OpDeliveryPoint deliveryPoint) {
        if (!Objects.isNull(deliveryPoint)) {
            OpTask opTask = new OpTask();
            opTask.setDispatchNo(newOrderRelease.getShipmentGid());
            opTask.setWaybillNo(newOrderRelease.getReleaseGid());
            opTask.setStatus(Task.Status.CREATED);
            if (deliveryPoint.getIsSeek().equals(YesOrNo.YES)) {
                opTask.setType(Task.Type.SEEK);
                opTask.setId(String.valueOf(snowFlakeId.nextId()));
                taskService.insert(opTask);
            }
            if (deliveryPoint.getIsMove().equals(YesOrNo.YES)) {
                opTask.setType(Task.Type.MOVE);
                opTask.setId(String.valueOf(snowFlakeId.nextId()));
                taskService.insert(opTask);
            }
            if (deliveryPoint.getIsPick().equals(YesOrNo.YES)) {
                opTask.setType(Task.Type.PICK);
                opTask.setId(String.valueOf(snowFlakeId.nextId()));
                taskService.insert(opTask);
            }
        }
    }

    private void updateOutboundNotice(OtmShipment shipment,List<Storehouse> orginHouses){
        Storehouse storehouse = getStorehouse(shipment.getOtmOrderReleaseList().get(0).getOriginLocationGid(),orginHouses);
        String status = judgeStatus(shipment.getOtmOrderReleaseList());
        if(status.equals(TableStatusEnum.STATUS_50.getCode())) {
            delOutNoticeByShipment(shipment,storehouse.getId());
        }else {
            //查询通知单头
            Wrapper<OutboundNoticeHeader> headerWrapper = new EntityWrapper<>();
            headerWrapper.eq("store_house_id",storehouse.getId());
            headerWrapper.eq("owner_order_no",shipment.getShipmentGid());
            headerWrapper.ne("status",TableStatusEnum.STATUS_50.getCode());

            OutboundNoticeHeader outboundNoticeHeader = outboundNoticeHeaderService.selectOne(headerWrapper);
            List<OutboundNoticeLine> outboundNoticeLines = null;
            if(Objects.nonNull(outboundNoticeHeader)) {
                //查询通知单明细
                Wrapper<OutboundNoticeLine> lineWrapper = new EntityWrapper<>();
                lineWrapper.eq("header_id", outboundNoticeHeader.getId());
                lineWrapper.ne("status", TableStatusEnum.STATUS_50.getCode());
                outboundNoticeLines = outboundNoticeLineService.selectList(lineWrapper);
            }

            List<OtmOrderRelease> insertOR = Lists.newArrayList();
            List<OtmOrderRelease> deleteOR = Lists.newArrayList();
            for(OtmOrderRelease otmOrderRelease : shipment.getOtmOrderReleaseList()){
                if(otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_50.getCode())){
                    if(isContainOutLine(otmOrderRelease,outboundNoticeLines)){
                        deleteOR.add(otmOrderRelease);
                    }
                } else {
                    if(!isContainOutLine(otmOrderRelease,outboundNoticeLines)){
                        insertOR.add(otmOrderRelease);
                    }
                }
            }

            if(Objects.isNull(outboundNoticeHeader)){
                insertOutboundNotice(shipment,insertOR);
            }else {
                List<OutboundNoticeLine> newNoticeLineList = Lists.newArrayList();
                for (OtmOrderRelease otmOrderRelease : insertOR ){
                    OutboundNoticeLine outboundNoticeLine = buildOutboundNoticeLine(otmOrderRelease,outboundNoticeHeader);
                    outboundNoticeLine.setRemarks("指令新增");
                    newNoticeLineList.add(outboundNoticeLine);
                }
                if(CollectionUtils.isNotEmpty(newNoticeLineList)){
                    outboundNoticeLineService.insertBatch(newNoticeLineList);
                }

                List<OutboundNoticeLine> delNoticeLines = Lists.newArrayList();
                for (OtmOrderRelease otmOrderRelease : deleteOR ){
                    OutboundNoticeLine outboundNoticeLine = getDelOutNoticeLine(otmOrderRelease,outboundNoticeLines);
                    if (Objects.nonNull(outboundNoticeLine)){
                        OutboundNoticeLine delOutboundNoticeLine = new OutboundNoticeLine();
                        delOutboundNoticeLine.setId(outboundNoticeLine.getId());
                        delOutboundNoticeLine.setStatus(TableStatusEnum.STATUS_50.getCode());
                        delOutboundNoticeLine.setRemarks("指令删除");
                        delPrepareLine(outboundNoticeLine.getId());//删除备料单
                        delNoticeLines.add(delOutboundNoticeLine);
                    }
                }
                if(CollectionUtils.isNotEmpty(delNoticeLines)){
                    outboundNoticeLineService.updateBatchById(delNoticeLines);
                }
            }
        }
    }

    /**
     * 出库通知单明细是否包含对应OR
     * @param otmOrderRelease
     * @param outboundNoticeLines
     * @return
     */
    private boolean isContainOutLine(OtmOrderRelease otmOrderRelease,List<OutboundNoticeLine> outboundNoticeLines){
        if(CollectionUtils.isEmpty(outboundNoticeLines)) return false;
        for (OutboundNoticeLine outboundNoticeLine:outboundNoticeLines){
            if(otmOrderRelease.getReleaseGid().equals(outboundNoticeLine.getLineSourceKey()) && otmOrderRelease.getVin().equals(outboundNoticeLine.getLotNo1())){
                return true;
            }
        }
        return false;
    }

    /**
     * 入库通知单是否包含对应OR
     * @param otmOrderRelease
     * @param inboundNoticeLines
     * @return
     */
    private boolean isContainInLine(OtmOrderRelease otmOrderRelease,List<InboundNoticeLine> inboundNoticeLines){
        if(CollectionUtils.isEmpty(inboundNoticeLines)) return false;
        for (InboundNoticeLine inboundNoticeLine:inboundNoticeLines){
            if(otmOrderRelease.getReleaseGid().equals(inboundNoticeLine.getLineSourceKey()) && otmOrderRelease.getVin().equals(inboundNoticeLine.getLotNo1())){
                return true;
            }
        }
        return false;
    }

    /**
     * 得到制定状态的OR汇总
     * @param statusCode 状态
     * @param otmOrderReleaseList OR
     * @return
     */
    private List<OtmOrderRelease> getOrderReleaseByStatus(String statusCode,List<OtmOrderRelease> otmOrderReleaseList){
        List<OtmOrderRelease> otmOrderReleases = Lists.newArrayList();
        for(OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
            if(otmOrderRelease.getDataStatus().equals(statusCode)){
                otmOrderReleases.add(otmOrderRelease);
            }
        }
        return otmOrderReleaseList;
    }

    private void updateInboundNotice(OtmShipment shipment,List<Storehouse> destHouses){
        Storehouse storehouse = getStorehouse(shipment.getOtmOrderReleaseList().get(0).getDestLocationGid(),
                destHouses);
        String status = judgeStatus(shipment.getOtmOrderReleaseList());
        if(status.equals(TableStatusEnum.STATUS_50.getCode())) {
            delInNoticeByShipment(shipment,storehouse.getId());
        }else {
            //查询通知单头
            Wrapper<InboundNoticeHeader> headerWrapper = new EntityWrapper<>();
            headerWrapper.eq("store_house_id",storehouse.getId());
            headerWrapper.eq("owner_order_no",shipment.getShipmentGid());
            headerWrapper.ne("status",TableStatusEnum.STATUS_50.getCode());
            InboundNoticeHeader inboundNoticeHeader = inboundNoticeHeaderService.selectOne(headerWrapper);

            List<InboundNoticeLine> inboundNoticeLines = null;
            if(Objects.nonNull(inboundNoticeHeader)){
                Wrapper<InboundNoticeLine> lineWrapper = new EntityWrapper<>();
                lineWrapper.eq("header_id",inboundNoticeHeader.getId());
                lineWrapper.ne("status",TableStatusEnum.STATUS_50.getCode());
                inboundNoticeLines = inboundNoticeLineService.selectList(lineWrapper);
            }

            List<OtmOrderRelease> insertOR = Lists.newArrayList();
            List<OtmOrderRelease> deleteOR = Lists.newArrayList();
            for(OtmOrderRelease otmOrderRelease : shipment.getOtmOrderReleaseList()){
                if(otmOrderRelease.getDataStatus().equals(TableStatusEnum.STATUS_50.getCode())){
                    if(isContainInLine(otmOrderRelease,inboundNoticeLines)){
                        deleteOR.add(otmOrderRelease);
                    }
                } else {
                    if(!isContainInLine(otmOrderRelease,inboundNoticeLines)){
                        insertOR.add(otmOrderRelease);
                    }
                }
            }


            if(Objects.isNull(inboundNoticeHeader)){
                insertInboundNotice(shipment,insertOR);
            }else {
                List<InboundNoticeLine> newNoticeLineList = Lists.newArrayList();
                for (OtmOrderRelease otmOrderRelease : insertOR ){
                    InboundNoticeLine inboundNoticeLine = buildInboundNoticeLine(otmOrderRelease,
                            inboundNoticeHeader);
                    inboundNoticeLine.setRemarks("指令新增");
                    newNoticeLineList.add(inboundNoticeLine);
                }
                if(CollectionUtils.isNotEmpty(newNoticeLineList)){
                    inboundNoticeLineService.insertBatch(newNoticeLineList);
                }

                List<InboundNoticeLine> delNoticeLines = Lists.newArrayList();
                for (OtmOrderRelease otmOrderRelease : deleteOR ){
                    InboundNoticeLine inboundNoticeLine = getDelInNoticeLine(otmOrderRelease,inboundNoticeLines);
                    if (Objects.nonNull(inboundNoticeLine)){
                        InboundNoticeLine delInboundNoticeLine = new InboundNoticeLine();
                        delInboundNoticeLine.setId(inboundNoticeLine.getId());
                        delInboundNoticeLine.setStatus(TableStatusEnum.STATUS_50.getCode());
                        delInboundNoticeLine.setRemarks("指令删除");
                        delNoticeLines.add(delInboundNoticeLine);
                    }
                }
                if(CollectionUtils.isNotEmpty(delNoticeLines)){
                    inboundNoticeLineService.updateBatchById(delNoticeLines);
                }
            }
        }
    }

    /**
     * 是否有工厂备料数据
     */
    private void checkIsExistFpiPre (List<InboundNoticeLine> newNoticeLineList, Long storeHouseId, String shipmentGid) {
        new Thread(() -> {
            try {
                for (InboundNoticeLine inboundNoticeLine : newNoticeLineList) {
                    if (!TableStatusEnum.STATUS_50.getCode().equals(inboundNoticeLine.getStatus())) {
                        FactoryPrepareInbound factoryEw = new FactoryPrepareInbound();
                        factoryEw.setVin(inboundNoticeLine.getLotNo1());
                        factoryEw.setPrepareStatus(TableStatusEnum.STATUS_10.getCode());
                        factoryEw.setStoreHouseId(storeHouseId);
                        FactoryPrepareInbound resFpi = factoryPrepareInboundMapper.selectOne(factoryEw);
                        if (null != resFpi && (storeHouseId.longValue() == factoryEw.getStoreHouseId().longValue())) {
                            FactoryPrepareInbound updateFpi = new FactoryPrepareInbound();
                            updateFpi.setId(resFpi.getId());
                            updateFpi.setOutboundTime(new Date());
                            updateFpi.setShipmentGid(shipmentGid);
                            updateFpi.setOutboundUser("下发指令自动库内转换");
                            updateFpi.setPrepareStatus(TableStatusEnum.STATUS_30.getCode());
                            factoryPrepareInboundMapper.updateById(updateFpi);
                            //iStockService.cleanStockData(resFpi.getStockId(), "备转正");
                            iStockService.deleteById(resFpi.getStockId());
                            skuMapper.deleteById(resFpi.getSkuId());
                            iInboundPutawayHeaderService.inboundNoticeLineId(inboundNoticeLine.getId(), PutAwayType.NOTICE_PUTAWAY, SourceSystem.AUTO,
                                    resFpi.getAreaId(), resFpi.getLocationId());
                            InboundNoticeLine updateInbound = new InboundNoticeLine();
                            updateInbound.setId(inboundNoticeLine.getId());
                            updateInbound.setRemarks("备转正");
                            inboundNoticeLineService.updateById(updateInbound);
                        }
                    }
                }
            } catch (Exception e) {
                LOGGER.error("无单修改异常{}", e.getMessage());
            }
        }).start();
    }

    /**
     * 汇集状态
     */
    private String judgeStatus(List<OtmOrderRelease> otmOrderReleaseList){

        if(isAppointStatus(TableStatusEnum.STATUS_0.getCode(),otmOrderReleaseList))
            return TableStatusEnum.STATUS_0.getCode();

        if(isAppointStatus(TableStatusEnum.STATUS_10.getCode(),otmOrderReleaseList))
            return TableStatusEnum.STATUS_10.getCode();

        if(isAppointStatus(TableStatusEnum.STATUS_50.getCode(),otmOrderReleaseList))
            return TableStatusEnum.STATUS_50.getCode();

        return TableStatusEnum.STATUS_20.getCode();

    }

    private boolean isAppointStatus(String status,List<OtmOrderRelease> otmOrderReleaseList){
        for(OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
            if(!otmOrderRelease.getDataStatus().equals(status)){
                return false;
            }
        }
        return true;
    }


    //匹配仓库
    private Storehouse getStorehouse(String code,List<Storehouse> storehouses){
        for(Storehouse storehouse : storehouses){
            if(code.equals(storehouse.getCode())) return storehouse;
        }
        return null;
    }


    /**
     * 比较指令，汇总Release状态
     * @param newOtmShipment
     * @param dbShipment
     * @return
     */
    //otm每天运单跟db下的运单作对比，如果otm里的运单已经在db中存在，则otm这个订单状态为不变 。不存在，otm这个订单状态新增
    private OtmShipment compareShipment (OtmShipment newOtmShipment, OtmShipment dbShipment) {
        List<OtmOrderRelease> otmOrderReleases = Lists.newArrayList();
        for (OtmOrderRelease otmOrderRelease : newOtmShipment.getOtmOrderReleaseList()) {
            if (isContainOrderRelease(otmOrderRelease, dbShipment.getOtmOrderReleaseList())) {
                isContainOrderInfo(otmOrderRelease, dbShipment.getOtmOrderReleaseList());
                otmOrderRelease.setDataStatus(TableStatusEnum.STATUS_0.getCode()); //不变
                otmOrderReleases.add(otmOrderRelease);
            } else {
                otmOrderRelease.setDataStatus(TableStatusEnum.STATUS_10.getCode()); //新增
                otmOrderReleases.add(otmOrderRelease);
            }
        }

        for (OtmOrderRelease otmOrderRelease : dbShipment.getOtmOrderReleaseList()) {
            if (!isContainOrderRelease(otmOrderRelease, newOtmShipment.getOtmOrderReleaseList())) {
                otmOrderRelease.setDataStatus(TableStatusEnum.STATUS_50.getCode());//删除
                otmOrderReleases.add(otmOrderRelease);
            }
        }
        newOtmShipment.setOtmOrderReleaseList(otmOrderReleases);
        return newOtmShipment;
    }

    /**
     * @param otmOrderRelease
     * @param otmOrderReleaseList
     * @return
     */
    private void isContainOrderInfo (OtmOrderRelease otmOrderRelease, List<OtmOrderRelease> otmOrderReleaseList) {
        for (OtmOrderRelease orderRelease : otmOrderReleaseList) {
            if (otmOrderRelease.getShipmentGid().equals(orderRelease.getShipmentGid())
                    && otmOrderRelease.getReleaseGid().equals(orderRelease.getReleaseGid())
                    && otmOrderRelease.getDestLocationGid().equals(orderRelease.getDestLocationGid())
                    && otmOrderRelease.getVin().equals(orderRelease.getVin())
            ) {
                String customerId = orderRelease.getCustomerId() == null ? "":orderRelease.getCustomerId();
                String cusOrderNo = orderRelease.getCusOrderNo() == null ? "":orderRelease.getCusOrderNo();
                String cusWaybillNo = orderRelease.getCusWaybillNo() == null ? "":orderRelease.getCusWaybillNo();
                String orderAtt = orderRelease.getOrderAtt() == null ? "":orderRelease.getOrderAtt();
                String cusVehicleType = orderRelease.getCusVehicleType() == null ? "":orderRelease.getCusVehicleType();
                String stanVehicleType = orderRelease.getStanVehicleType() == null ? "":orderRelease.getStanVehicleType();
                if (!((otmOrderRelease.getCustomerId() == null ? "" : otmOrderRelease.getCustomerId()).equals(customerId)
                        && (otmOrderRelease.getCusOrderNo() == null ? "" : otmOrderRelease.getCusOrderNo()).equals(cusOrderNo)
                        && (otmOrderRelease.getCusWaybillNo() == null ? "" : otmOrderRelease.getCusWaybillNo()).equals(cusWaybillNo)
                        && (otmOrderRelease.getOrderAtt() == null ? "" : otmOrderRelease.getOrderAtt()).equals(orderAtt)
                        && (otmOrderRelease.getCusVehicleType() == null ? "" : otmOrderRelease.getCusVehicleType()).equals(cusVehicleType)
                        && (otmOrderRelease.getStanVehicleType() == null ? "" : otmOrderRelease.getStanVehicleType()).equals(stanVehicleType))) {
                    iOrderReleaseService.updateRelease(otmOrderRelease);
                }
            }
        }
    }

    private boolean isContainOrderRelease (OtmOrderRelease otmOrderRelease, List<OtmOrderRelease> otmOrderReleaseList) {
        for (OtmOrderRelease orderRelease : otmOrderReleaseList) {
            if (otmOrderRelease.getShipmentGid().equals(orderRelease.getShipmentGid())
                    && otmOrderRelease.getReleaseGid().equals(orderRelease.getReleaseGid())
                    && otmOrderRelease.getDestLocationGid().equals(orderRelease.getDestLocationGid())
                    && otmOrderRelease.getVin().equals(orderRelease.getVin())
            ) {
                return true;
            }
        }
        return false;
    }

    /**
     * 删除指令
     * @param otmShipment
     */
    private void delShipment(OtmShipment otmShipment){

        OtmShipment delOtmShipment = new OtmShipment();
        delOtmShipment.setId(otmShipment.getId());
        delOtmShipment.setStatus(TableStatusEnum.STATUS_50.getCode());
        delOtmShipment.setRemarks("指令删除");
        otmShipmentService.updateById(delOtmShipment);

        for (OtmOrderRelease otmOrderRelease : otmShipment.getOtmOrderReleaseList()){
            OtmOrderRelease delOtmOrderRelease = new OtmOrderRelease();
            delOtmOrderRelease.setId(otmOrderRelease.getId());
            delOtmOrderRelease.setRemarks("指令删除");
            delOtmOrderRelease.setStatus(TableStatusEnum.STATUS_50.getCode());
            otmOrderReleaseService.updateById(delOtmOrderRelease);
        }
    }

    /**
     * 根据OR删除对应任务
     * @param otmOrderRelease
     */
    private void delTask(OtmOrderRelease otmOrderRelease){
        //任务单据的状态
        EntityWrapper<OpTask> taskEW = new EntityWrapper<>();
        taskEW.eq("waybill_no", otmOrderRelease.getReleaseGid())
                .eq("dispatch_no",otmOrderRelease.getShipmentGid())
                .notIn("status", TableStatusEnum.STATUS_50.getCode());
        OpTask task = new OpTask();
        task.setStatus(TableStatusEnum.STATUS_50.getCode());
        taskService.update(task, taskEW);
    }

    /**
     * 根据分组指令删除出库通知单
     * @param shipment
     */
    private void delOutNoticeByShipment(OtmShipment shipment,Long sorehouseId){

        Wrapper<OutboundNoticeHeader> ew = new EntityWrapper<>();
        ew.eq("owner_order_no",shipment.getShipmentGid());
        if(Objects.nonNull(sorehouseId)){
            ew.eq("store_house_id",sorehouseId);
        }
        List<OutboundNoticeHeader> outboundNoticeHeaderList = outboundNoticeHeaderService.selectList(ew);
        for (OutboundNoticeHeader outboundNoticeHeader : outboundNoticeHeaderList){
            Wrapper<OutboundNoticeLine> outLine = new EntityWrapper<>();
            outLine.eq("header_id",outboundNoticeHeader.getId());
            outLine.ne("status",TableStatusEnum.STATUS_50.getCode());
            List<OutboundNoticeLine> outboundNoticeLines = outboundNoticeLineService.selectList(outLine);
            for (OutboundNoticeLine outboundNoticeLine : outboundNoticeLines){

                //删除备料单明细
                delPrepareLine(outboundNoticeLine.getId());

                //更新通知单明细为已删除
                OutboundNoticeLine updateNoticeLine = new OutboundNoticeLine();
                updateNoticeLine.setId(outboundNoticeLine.getId());
                updateNoticeLine.setStatus(TableStatusEnum.STATUS_50.getCode());
                updateNoticeLine.setRemarks("指令删除");
                // 记录当前状态
                outboundNoticeLineService.updateById(updateNoticeLine);
            }

            OutboundNoticeHeader updateNoticeHeader = new OutboundNoticeHeader();
            updateNoticeHeader.setId(outboundNoticeHeader.getId());
            updateNoticeHeader.setStatus(TableStatusEnum.STATUS_50.getCode());
            updateNoticeHeader.setRemarks("指令删除");
            //记录当前状态
            outboundNoticeHeaderService.updateById(updateNoticeHeader);
        }
    }

    private void delPrepareLine(Long noticeLineId){
        //查询明细对应的未完成的备料单
        List<String> statusList = Lists.newArrayList();
        statusList.add(TableStatusEnum.STATUS_10.getCode());
        statusList.add(TableStatusEnum.STATUS_20.getCode());
        Wrapper<OutboundPrepareLine> prepareLineWrapper = new EntityWrapper<>();
        prepareLineWrapper.eq("notice_line_id",noticeLineId);
        prepareLineWrapper.in("status",statusList);
        OutboundPrepareLine prepareLine = outboundPrepareLineService.selectOne(prepareLineWrapper);
        if(Objects.nonNull(prepareLine)){
            //更新备料单为删除状态
            OutboundPrepareLine updatePrepareLine = new OutboundPrepareLine();
            updatePrepareLine.setId(prepareLine.getId());
            updatePrepareLine.setStatus(TableStatusEnum.STATUS_40.getCode());
            updatePrepareLine.setRemarks("指令删除");
            outboundPrepareLineService.updateById(updatePrepareLine);
        }
    }

    /**
     * 按发货仓库分组调度指令
     * @param outHouses
     * @param otmShipment
     * @return
     */
    private List<OtmShipment> getOutboundShipment(List<Storehouse> outHouses,OtmShipment otmShipment){
        List<OtmShipment> otmShipmentList = Lists.newArrayList();

        for(Storehouse house : outHouses){
            List<OtmOrderRelease> otmOrderReleaseList = getORListByOutHouse(house.getCode(),
                    otmShipment.getOtmOrderReleaseList());
            if(CollectionUtils.isNotEmpty(otmOrderReleaseList)){
                for (OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
                    otmOrderRelease.setOutboundHouseId(house.getId());
                }
            }
            OtmShipment shipment = buildShipment(otmShipment,otmOrderReleaseList);
            if(Objects.nonNull(shipment)) otmShipmentList.add(shipment);
        }

        return otmShipmentList;
    }

    /**
     * 根据发货仓库汇总OR
     * @param houseCode
     * @param otmOrderReleaseList
     * @return
     */
    private List<OtmOrderRelease> getORListByOutHouse(String houseCode,
                                                      List<OtmOrderRelease> otmOrderReleaseList){
        List<OtmOrderRelease> otmOrderReleases = Lists.newArrayList();
        for(OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
            if(houseCode.equals(otmOrderRelease.getOriginLocationGid())){
                otmOrderReleases.add(otmOrderRelease);
            }
        }
        return otmOrderReleases;
    }

    /**
     * 按收货仓库分组调度指令
     * @param inHouses
     * @param otmShipment
     * @return
     */
    private List<OtmShipment> getInboundShipment(List<Storehouse> inHouses,OtmShipment otmShipment){
        List<OtmShipment> otmShipmentList = Lists.newArrayList();
        for(Storehouse house : inHouses){
            List<OtmOrderRelease> otmOrderReleaseList = getORListByInHouse(house.getCode(),
                    otmShipment.getOtmOrderReleaseList());
            if(CollectionUtils.isNotEmpty(otmOrderReleaseList)){
                for (OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
                    otmOrderRelease.setInboundHouseId(house.getId());
                }

            }
            OtmShipment shipment = buildShipment(otmShipment,otmOrderReleaseList);
            if(Objects.nonNull(shipment)) otmShipmentList.add(shipment);
        }
        return otmShipmentList;
    }

    /**
     * 通过收货仓库汇总OR
     * @param houseCode
     * @param otmOrderReleaseList
     * @return
     */
    private List<OtmOrderRelease> getORListByInHouse(String houseCode,
                                                      List<OtmOrderRelease> otmOrderReleaseList){
        List<OtmOrderRelease> otmOrderReleases = Lists.newArrayList();
        for(OtmOrderRelease otmOrderRelease : otmOrderReleaseList){
            if(houseCode.equals(otmOrderRelease.getDestLocationGid())){
                otmOrderReleases.add(otmOrderRelease);
            }
        }
        return otmOrderReleases;
    }

    /**
     * 构建指令
     * @param otmShipment
     * @param otmOrderReleaseList
     * @return
     */
    private OtmShipment buildShipment(OtmShipment otmShipment,List<OtmOrderRelease> otmOrderReleaseList){
        if(Objects.nonNull(otmOrderReleaseList) && otmOrderReleaseList.size()>0){
            OtmShipment shipment = new OtmShipment();
            BeanUtils.copyProperties(otmShipment,shipment);
            shipment.setOtmOrderReleaseList(otmOrderReleaseList);
            return shipment;
        }
        return null;
    }

    /**
     * 根据指令删除入库通知单
     * @param shipment
     */
    private void delInNoticeByShipment(OtmShipment shipment,Long sorehouseId){
        Wrapper<InboundNoticeHeader> ew = new EntityWrapper<>();
        ew.eq("owner_order_no",shipment.getShipmentGid());
        if(Objects.nonNull(sorehouseId)){
            ew.eq("store_house_id",sorehouseId);
        }

        List<InboundNoticeHeader> inboundNoticeHeaderList = inboundNoticeHeaderService.selectList(ew);
        for (InboundNoticeHeader inboundNoticeHeader : inboundNoticeHeaderList){
            Wrapper<InboundNoticeLine> outLine = new EntityWrapper<>();
            outLine.eq("header_id",inboundNoticeHeader.getId());
            outLine.ne("status",TableStatusEnum.STATUS_50.getCode());
            List<InboundNoticeLine> inboundNoticeLines = inboundNoticeLineService.selectList(outLine);
            for (InboundNoticeLine outboundNoticeLine : inboundNoticeLines){
                //更新通知单明细为已删除
                InboundNoticeLine updateNoticeLine = new InboundNoticeLine();
                updateNoticeLine.setId(outboundNoticeLine.getId());
                updateNoticeLine.setStatus(TableStatusEnum.STATUS_50.getCode());
                updateNoticeLine.setRemarks("指令删除");
                // 记录当前状态
                inboundNoticeLineService.updateById(updateNoticeLine);
            }

            InboundNoticeHeader updateNoticeHeader = new InboundNoticeHeader();
            updateNoticeHeader.setId(inboundNoticeHeader.getId());
            updateNoticeHeader.setStatus(TableStatusEnum.STATUS_50.getCode());
            updateNoticeHeader.setRemarks("指令删除");
            //记录当前状态
            inboundNoticeHeaderService.updateById(updateNoticeHeader);
        }
    }

    /**
     * 得到数据库中的OTM指令
     * @param shipmentDTO
     * @return
     */
    private OtmShipment getDBShipment(ShipmentDTO shipmentDTO) {
        //查询OtmShipment
        Wrapper<OtmShipment> shipEw = new EntityWrapper<>();
        shipEw.eq("shipment_gid", shipmentDTO.getShipmentId())
                .notIn("status", TableStatusEnum.STATUS_50.getCode())
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        OtmShipment shipment = otmShipmentService.selectOne(shipEw);

        if(Objects.nonNull(shipment)){
            //查询OtmOrderRelease
            Wrapper<OtmOrderRelease> orEw = new EntityWrapper<>();
            orEw.eq("shipment_gid", shipmentDTO.getShipmentId())
                    .notIn("status", TableStatusEnum.STATUS_50.getCode())
                    .orderBy("gmt_create", false)
                    .orderBy("id", false);
            List<OtmOrderRelease> orList = otmOrderReleaseService.selectList(orEw);

            shipment.setOtmOrderReleaseList(orList);
        }

        return shipment;
    }

    /**
     * 构建导入日志
     * @param dto
     * @param logLineCache
     * @param orderType
     * @return
     */
    private ItfImplogHeader getLogHeader(ShipmentDTO dto, HashMap<String, Long> logLineCache, String orderType) {
        List<ShipTaskDTO> taskDTOList = dto.getShipTaskDTOList();
        ItfImplogHeader logHeader = new ItfImplogHeader();
        logHeader.setId(snowFlakeId.nextId());
        if (CollectionUtils.isNotEmpty(taskDTOList)) {
            ShipTaskDTO task = taskDTOList.get(0);
            logHeader.setOwnerId(task.getCustomerId());
            logHeader.setOwnerOrderNo(task.getCusOrderNo());
            logHeader.setRecvHouseId(task.getDestLocationId());
            logHeader.setDeliveryHouseId(task.getOriginLocationId());
            logHeader.setDeliveryHouseName(task.getOriginLocationName());
            logHeader.setRecvHouseName(task.getDestLocationName());
        }
        logHeader.setType(orderType);
        logHeader.setOrderDate(new Date());
        logHeader.setCarrierId(dto.getServiceProviderId());
        logHeader.setCarrierName(dto.getServiceProviderName());
        logHeader.setTransportMethod(dto.getTransportModeId());
        logHeader.setPlateNumber(dto.getPlateNo());
        logHeader.setDriverName(dto.getDriverName());
        logHeader.setDriverPhone(dto.getDriverMoble());
        logHeader.setExpectOutDateLower(dto.getExpcetShipDate());
        logHeader.setExpectOutDateUpper(dto.getExpcetShipDate());
        logHeader.setExpectInDateLower(dto.getExpectInboundDate());
        logHeader.setExpectInDateUpper(dto.getExpectInboundDate());
        logHeader.setUom(MeasureUnit.TAI);
        logHeader.setExpectSumQty(CollectionUtils.isEmpty(taskDTOList) ? BigDecimal.ZERO : new BigDecimal(taskDTOList.size()));
        logHeader.setLineCount(CollectionUtils.isEmpty(taskDTOList) ? 0 : taskDTOList.size());
        logHeader.setSourceSystem(SourceSystem.OTM);
        logHeader.setSourceKey(dto.getShipmentId());
        logHeader.setSourceNo(dto.getShipmentId());
        logHeader.setStatus(TableStatusEnum.STATUS_10.getCode());
        logHeader.setRemarks("成功");
        logHeader.setImportStatus(TableStatusEnum.STATUS_1.getCode());
        logHeader.setImportRemarks("导入成功");
        logHeader.setImportTime(new Date());
        logHeader.setUserDef8(SysSourceEnum.NORMAL_TYPE.getName());
        logHeader.setUserDef9(SysSourceEnum.OTM_CREATE.getName());
        logHeader.setGmtCreate(null);
        logHeader.setGmtModified(null);
        if (CollectionUtils.isNotEmpty(taskDTOList)) {
            for (ShipTaskDTO taskDTO : taskDTOList) {
                ItfImplogLine logLine = new ItfImplogLine();
                logLine.setId(snowFlakeId.nextId());
                logLine.setHeaderId(logHeader.getId());
                logLine.setLineSourceKey(taskDTO.getTaskId());
                logLine.setLineSourceNo(taskDTO.getTaskId());
                logLine.setOwnerId(taskDTO.getCustomerId());
                logLine.setOwnerOrderNo(taskDTO.getCusOrderNo());
                logLine.setMaterielId(taskDTO.getStanVehicleType());
                logLine.setRemarks("导入成功");
                logLine.setUom(MeasureUnit.TAI);
                logLine.setExpectQty(BigDecimal.ONE);
                logLine.setLotNo1(taskDTO.getVin());
                logLine.setUserDef5(taskDTO.getPickupIsAppt());
                logLine.setUserDef6(taskDTO.getIsModVehicle());//是否改装车
                logLine.setUserDef7(taskDTO.getOrderAtt());
                logLine.setUserDef8(SysSourceEnum.NORMAL_TYPE.getName());
                logLine.setUserDef9(SysSourceEnum.OTM_CREATE.getName());
                logLine.setGmtCreate(null);
                logLine.setGmtModified(null);
                logHeader.addItfImplogLine(logLine);
                logLineCache.put(taskDTO.getTaskId(), logLine.getId());
            }
        }
        return logHeader;
    }


    /**
     * 判断出入库类型(出库、入库、移库)
     * @param outHouses
     * @param inHouses
     * @return
     */
    private String acquireOrderType(List<Storehouse> outHouses, List<Storehouse> inHouses) {
        if (CollectionUtils.isNotEmpty(outHouses) && CollectionUtils.isNotEmpty(inHouses)) {
            return OrderType.MOVEBOUND;
        } else if (CollectionUtils.isNotEmpty(outHouses)) {
            return OrderType.OUTBOUND;
        } else if (CollectionUtils.isNotEmpty(inHouses)) {
            return OrderType.INBOUND;
        } else {
            return OrderType.OTHER;
        }
    }

    /**
     * 构建OTM的shipment和orderRelease
     */
    private OtmShipment getOtmShipment(ShipmentDTO dto, ItfImplogHeader logHeader, HashMap<String, Long> logLineCache) {
        OtmShipment osm = new OtmShipment();
        osm.setShipmentGid(dto.getShipmentId());
        osm.setShipmentType(dto.getShipmentType());
        osm.setTransactionCode(dto.getTransactionCode());
        osm.setTransportModeGid(dto.getTransportModeId());
        osm.setServiceProviderGid(dto.getServiceProviderId());
        osm.setServiceProviderName(dto.getServiceProviderName());
        osm.setDriverGid(dto.getDriverId());
        osm.setDriverName(dto.getDriverName());
        osm.setDriverPhone(dto.getDriverMoble());
        osm.setPlateNo(dto.getPlateNo());
        osm.setTrailerNo(dto.getTrailerNo());
        osm.setTotalShipCount(dto.getTotalShipCount());
        osm.setExpectInboundDate(dto.getExpectInboundDate());
        osm.setExpectReceiptDate(dto.getExpectReceiptDate());
        osm.setExpcetShipDate(dto.getExpcetShipDate());
        osm.setExpectArriveDate(dto.getExpectArriveDate());
        osm.setLogHeaderId(logHeader.getId());
        osm.setSourceKey(dto.getShipmentId());
        osm.setSourceNo(dto.getShipmentId());
        osm.setOriginLocationGid(dto.getOriginLocationId());
        osm.setOriginLocationName(dto.getOriginLocationName());
        osm.setOriginLocationProvince(dto.getOriginLocationProvince());
        osm.setOriginLocationCity(dto.getOriginLocationCity());
        osm.setOriginLocationCounty(dto.getOriginLocationCounty());
        osm.setOriginLocationAddress(dto.getOriginLocationAddress());
        osm.setDestLocationId(dto.getDestLocationId());
        osm.setDestLocationName(dto.getDestLocationName());
        osm.setDestLocationProvince(dto.getDestLocationProvince());
        osm.setDestLocationCity(dto.getDestLocationCity());
        osm.setDestLocationCounty(dto.getDestLocationCounty());
        osm.setDestLocationAddress(dto.getDestLocationAddress());
        osm.setRemarks(dto.getRemarks());
        osm.setStatus(dto.getStatus());// 取OTM 指令状态
        osm.setGmtCreate(null);
        osm.setGmtModified(null);
        osm.setBoundType(logHeader.getType());
        List<ShipTaskDTO> dtoList = dto.getShipTaskDTOList();
        if (CollectionUtils.isNotEmpty(dtoList)) {
            for (ShipTaskDTO task : dtoList) {
                OtmOrderRelease otr = new OtmOrderRelease();
                otr.setReleaseGid(task.getTaskId());
                otr.setShipmentGid(task.getShipmentId());
                otr.setCustomerId(task.getCustomerId());
                otr.setCusOrderNo(task.getCusOrderNo()); // 调整存储 客户运单号
                otr.setCusWaybillNo(task.getCusWaybillNo());
                otr.setCusTransMode(task.getCusTransMode());
                otr.setIsUrgent(task.getIsUrgent());
                otr.setPickupIsAppt(task.getPickupIsAppt());
                otr.setOrderAtt(task.getOrderAtt());
                otr.setExpectInboundDate(task.getExpectInboundDate());
                otr.setExpectReceiptDate(task.getExpectReceiptDate());
                otr.setExpcetShipDate(task.getExpcetShipDate());
                otr.setExpectArriveDate(task.getExpectArriveDate());
                otr.setLogLineId(logLineCache.get(task.getTaskId()));
                otr.setSourceKey(task.getTaskId());
                otr.setSourceNo(task.getTaskId());
                otr.setOriginLocationGid(task.getOriginLocationId());
                otr.setOriginLocationName(task.getOriginLocationName());
                otr.setOriginLocationProvince(task.getOriginLocationProvince());
                otr.setOriginLocationCity(task.getOriginLocationCity());
                otr.setOriginLocationCounty(task.getOriginLocationCounty());
                otr.setOriginLocationAddress(task.getOriginLocationAddress());
                otr.setDestLocationGid(task.getDestLocationId());
                otr.setDestLocationName(task.getDestLocationName());
                otr.setDestLocationProvince(task.getDestLocationProvince());
                otr.setDestLocationCity(task.getDestLocationCity());
                otr.setDestLocationCounty(task.getDestLocationCounty());
                otr.setDestLocationAddress(task.getDestLocationAddress());
                if (StringUtils.isNotBlank(task.getOrderDestAddress())) {
                    otr.setOrderDestAddress(task.getOrderDestAddress());
                }
                otr.setCusVehicleType(task.getCusVehicleType());
                otr.setVehicleDescribe(task.getVehicleDescribe());
                otr.setStanVehicleType(task.getStanVehicleType());
                otr.setVin(task.getVin());
                otr.setIsModVehicle(task.getIsModVehicle());
                otr.setModVehicleSize(task.getModVehicleSize());
                otr.setQrCode(task.getQrCode());
                otr.setRemarks(task.getRemarks());
                otr.setStatus(task.getStatus());  // 取task 运单的状态
                otr.setOrderNo(task.getOrderNo());
                otr.setGmtModified(null);
                otr.setGmtCreate(null);
                osm.addOtmOrderRelease(otr);
            }
        }

        return osm;
    }


    /**
     * 创建出库通知单
     */
    private void insertOutboundNotice(OtmShipment otmShipment, List<OtmOrderRelease> otmOrderReleaseList) {
        if (Objects.isNull(otmOrderReleaseList) || otmOrderReleaseList.size() == 0) {
            throw new BaseException("入库运单为空");
        }
        OutboundNoticeHeader outboundNoticeHeader = new OutboundNoticeHeader();
        outboundNoticeHeader.setId(snowFlakeId.nextId());
        outboundNoticeHeader.setStoreHouseId(otmOrderReleaseList.get(0).getOutboundHouseId());
        outboundNoticeHeader.setNoticeNo(businessDocNumberService.getOutboundNoticeNo());
        outboundNoticeHeader.setOwnerOrderNo(otmShipment.getShipmentGid());
        outboundNoticeHeader.setOrderDate(otmShipment.getExpectInboundDate());
        outboundNoticeHeader.setCarrierId(otmShipment.getServiceProviderGid());
        outboundNoticeHeader.setCarrierName(otmShipment.getServiceProviderName());
        outboundNoticeHeader.setTransportMethod(otmShipment.getTransportModeGid());
        outboundNoticeHeader.setPlateNumber(otmShipment.getPlateNo());
        outboundNoticeHeader.setDriverName(otmShipment.getDriverName());
        outboundNoticeHeader.setDriverPhone(otmShipment.getDriverPhone());
        outboundNoticeHeader.setExpectShipDateLower(otmShipment.getExpcetShipDate());
        outboundNoticeHeader.setUom(MeasureUnit.TAI);
        outboundNoticeHeader.setExpectSumQty(new BigDecimal(otmOrderReleaseList.size()));
        outboundNoticeHeader.setLineCount(otmOrderReleaseList.size());
        outboundNoticeHeader.setLogHeaderId(otmShipment.getLogHeaderId());
        outboundNoticeHeader.setSourceKey(otmShipment.getShipmentGid());
        outboundNoticeHeader.setSourceNo(otmShipment.getShipmentGid());
        outboundNoticeHeader.setOutboundSumQty(BigDecimal.ZERO);
        outboundNoticeHeader.setStatus(TableStatusEnum.STATUS_10.getCode());

        for (OtmOrderRelease otmOrderRelease : otmOrderReleaseList) {
            OutboundNoticeLine outboundNoticeLine = buildOutboundNoticeLine(otmOrderRelease,outboundNoticeHeader);
            outboundNoticeHeader.addOutboundNoticeLine(outboundNoticeLine);
        }
        outboundNoticeHeaderService.insertOutboundNotice(outboundNoticeHeader);
    }

    /**
     * 构建出库通知单明细
     * @param otmOrderRelease
     * @param outboundNoticeHeader
     * @return
     */
    private OutboundNoticeLine buildOutboundNoticeLine(OtmOrderRelease otmOrderRelease,
                                                       OutboundNoticeHeader outboundNoticeHeader){
        OutboundNoticeLine outboundNoticeLine = new OutboundNoticeLine();
        outboundNoticeLine.setId(snowFlakeId.nextId());
        outboundNoticeLine.setHeaderId(outboundNoticeHeader.getId());
        outboundNoticeLine.setOwnerId(otmOrderRelease.getCustomerId());
        outboundNoticeLine.setOwnerOrderNo(otmOrderRelease.getCusOrderNo());
        outboundNoticeLine.setLogLineId(otmOrderRelease.getLogLineId());
        outboundNoticeLine.setLineSourceKey(otmOrderRelease.getReleaseGid());
        outboundNoticeLine.setLineSourceNo(otmOrderRelease.getReleaseGid());
        outboundNoticeLine.setMaterielId(otmOrderRelease.getStanVehicleType());
        outboundNoticeLine.setUom(outboundNoticeHeader.getUom());
        outboundNoticeLine.setExpectQty(BigDecimal.ONE);
        outboundNoticeLine.setOutboundQty(BigDecimal.ZERO);
        outboundNoticeLine.setLotNo1(otmOrderRelease.getVin());
        outboundNoticeLine.setStatus(Status.Inbound.NOT);
        return outboundNoticeLine;
    }

    /**
     * 得到需删除的出库通知单明细
     * @param otmOrderRelease
     * @param outboundNoticeLines
     * @return
     */
    private OutboundNoticeLine getDelOutNoticeLine(OtmOrderRelease otmOrderRelease,
                                                List<OutboundNoticeLine> outboundNoticeLines){
        for (OutboundNoticeLine outboundNoticeLine : outboundNoticeLines){
            if(outboundNoticeLine.getLineSourceKey().equals(otmOrderRelease.getReleaseGid())){
                return outboundNoticeLine;
            }
        }
        return null;
    }

    /**
     * 创建入库通知单
     */
    private void insertInboundNotice(OtmShipment otmShipment, List<OtmOrderRelease> otmOrderReleaseList) {

        if (Objects.isNull(otmOrderReleaseList) || otmOrderReleaseList.size() == 0) throw new BaseException("入库运单为空");

        InboundNoticeHeader inboundNoticeHeader = new InboundNoticeHeader();
        inboundNoticeHeader.setId(snowFlakeId.nextId());
        inboundNoticeHeader.setStoreHouseId(otmOrderReleaseList.get(0).getInboundHouseId());
        inboundNoticeHeader.setNoticeNo(businessDocNumberService.getInboundNoticeNo());
        inboundNoticeHeader.setOwnerOrderNo(otmShipment.getShipmentGid());
        inboundNoticeHeader.setOrderDate(otmShipment.getExpectInboundDate());
        inboundNoticeHeader.setCarrierId(otmShipment.getServiceProviderGid());
        inboundNoticeHeader.setCarrierName(otmShipment.getServiceProviderName());
        inboundNoticeHeader.setTransportMethod(otmShipment.getTransportModeGid());
        inboundNoticeHeader.setPlateNumber(otmShipment.getPlateNo());
        inboundNoticeHeader.setDriverName(otmShipment.getDriverName());
        inboundNoticeHeader.setDriverPhone(otmShipment.getDriverPhone());
        inboundNoticeHeader.setExpectRecvDateLower(otmShipment.getExpectArriveDate());
        inboundNoticeHeader.setUom(MeasureUnit.TAI);
        inboundNoticeHeader.setExpectSumQty(new BigDecimal(otmOrderReleaseList.size()));
        inboundNoticeHeader.setLineCount(otmOrderReleaseList.size());
        inboundNoticeHeader.setLogHeaderId(otmShipment.getLogHeaderId());
        inboundNoticeHeader.setSourceKey(otmShipment.getShipmentGid());
        inboundNoticeHeader.setSourceNo(otmShipment.getShipmentGid());
        inboundNoticeHeader.setRemarks("指令新增");
        inboundNoticeHeader.setInboundSumQty(BigDecimal.ZERO);
        inboundNoticeHeader.setUserCreate(SysSourceEnum.OTM_CREATE.getName());
        inboundNoticeHeader.setUserModified(SysSourceEnum.OTM_CREATE.getName());

        for (OtmOrderRelease otmOrderRelease : otmOrderReleaseList) {
            InboundNoticeLine inboundNoticeLine = buildInboundNoticeLine(otmOrderRelease,inboundNoticeHeader);
            inboundNoticeHeader.addInboundNoticeLine(inboundNoticeLine);
        }
        inboundNoticeHeaderService.insertInboundNotice(inboundNoticeHeader);
        //是否有工厂未备料入库数据（逻辑处理）
        if(OtmShipmentType.PICK_UP.equals(otmShipment.getShipmentType())){
            if(null != inboundNoticeHeader.getStoreHouseId()){
                checkIsExistFpiPre(inboundNoticeHeader.getInboundNoticeLineList(),inboundNoticeHeader.getStoreHouseId(),otmShipment.getShipmentGid());
            }
        }
    }


    /**
     * 构建出库通知单明细
     * @param otmOrderRelease
     * @param inboundNoticeHeader
     * @return
     */
    private InboundNoticeLine buildInboundNoticeLine(OtmOrderRelease otmOrderRelease,
                                                       InboundNoticeHeader inboundNoticeHeader){
        InboundNoticeLine inboundNoticeLine = new InboundNoticeLine();
        inboundNoticeLine.setId(snowFlakeId.nextId());
        inboundNoticeLine.setHeaderId(inboundNoticeHeader.getId());
        inboundNoticeLine.setOwnerId(otmOrderRelease.getCustomerId());
        inboundNoticeLine.setOwnerOrderNo(otmOrderRelease.getCusOrderNo());//调整存储客户运单号
        inboundNoticeLine.setLogLineId(otmOrderRelease.getLogLineId());
        inboundNoticeLine.setLineSourceKey(otmOrderRelease.getReleaseGid());
        inboundNoticeLine.setLineSourceNo(otmOrderRelease.getReleaseGid());
        inboundNoticeLine.setMaterielId(otmOrderRelease.getStanVehicleType());
        inboundNoticeLine.setUom(inboundNoticeHeader.getUom());
        inboundNoticeLine.setExpectQty(BigDecimal.ONE);
        inboundNoticeLine.setInboundQty(BigDecimal.ZERO);
        inboundNoticeLine.setLotNo1(otmOrderRelease.getVin());
        //加入调度车型 大中小 放入lot_no5中 hgy 20200804
        inboundNoticeLine.setLotNo5(otmOrderRelease.getModVehicleSize());
        inboundNoticeLine.setStatus(Status.Inbound.NOT);
        inboundNoticeLine.setRemarks("指令新增");
        return inboundNoticeLine;
    }

    /**
     * 得到需删除的入库通知单明细
     * @param otmOrderRelease
     * @param inboundNoticeLines
     * @return
     */
    private InboundNoticeLine getDelInNoticeLine(OtmOrderRelease otmOrderRelease,
                                                List<InboundNoticeLine> inboundNoticeLines){
        for (InboundNoticeLine inboundNoticeLine : inboundNoticeLines){
            if(inboundNoticeLine.getLineSourceKey().equals(otmOrderRelease.getReleaseGid())){
                return inboundNoticeLine;
            }
        }
        return null;
    }

}
